/**
 * 二维矩阵，每走一步消耗一点能量，
 * 其中N个格子有能量，走到该格，就可以设置为该能量
 * 问能否从起点到终点
 * 因为规模较小，对有能量的格子建图
 * for每一格有能量的格子：
 *     广搜，看它能够到达哪些有能量的格子（包括终点）
 * 这一步需要O(NHW)
 * 然后再在能量格子的图上再做一个广搜，这一步不会超过O(HW)
 */
#include <bits/stdc++.h>
using namespace std;

using llt = long long;
using vi = vector<int>;
using pii = pair<int, int>;
using vpii = vector<pii>;

template<typename T>
void input(vector<T> & a, int n){
    a.assign(n + 1, {});
    for(int i=1;i<=n;++i) cin >> a[i];
    return;
}

const int DR[] = {-1, 1, 0, 0};
const int DC[] = {0, 0, -1, 1};

int N;
int H, W;
vector<string> Board;
vector<pair<pii, int>> E;
vector<vi> Energy;
map<pii, int> Pos2Vertex;
vector<vi> G;
bool Possible;

void proc(int u){
    auto pos = E[u].first;
    auto w = E[u].second;
    u += 1;
    
    vector<vi> flag(H,vi(W, 0));
    queue<pii> q;
    q.push(pos);
    flag[pos.first][pos.second] = 1;
    for(int i=0;i<w;++i){
        int sz = q.size();
        while(sz--){
            auto h = q.front(); q.pop();
            for(int nr,nc,j=0;j<4;++j){
                nr = DR[j] + h.first;
                nc = DC[j] + h.second;
                if(0 <= nr and nr < H and 0 <= nc and nc < W and 0 == flag[nr][nc] and '#' != Board[nr][nc]){
                    flag[nr][nc] = 1;
                    if(Energy[nr][nc]){
                        auto it = Pos2Vertex.find(pii{nr, nc});
                        assert(it != Pos2Vertex.end());
                        G[u].push_back(it->second);                        
                    }
                    if('T' == Board[nr][nc]){
                        G[u].push_back(N + 1);
                        Possible = true;
                        continue;
                    }
                    q.push({nr, nc});                    
                }
            }
        }
    }
    return;
}

bool proc(){
    Possible = false;

    G.assign(N + 2, {});
    for(int i=0;i<N;++i){
        proc(i);        
    }

    if(not Possible) return false;

    int sr = -1, sc = -1;
    for(int i=0;i<H;++i)for(int j=0;j<W;++j){
        if('S' == Board[i][j]){
            sr = i, sc = j; 
            goto L;
        }
    }
L:
    assert(sr != -1 and sc != -1);
    auto it = Pos2Vertex.find(pii{sr, sc});
    if(it == Pos2Vertex.end()) return false;


    queue<int> q;
    vi flag(N + 2, 0);
    flag[it->second] == 1;
    q.push(it->second);
    assert(it->second != N + 1);
    int sz;
    while(sz = q.size()){
        while(sz--){
            auto h = q.front(); q.pop();
            for(auto v : G[h]){
                if(v == N + 1) return true;
                if(0 == flag[v]){
                    q.push(v);
                    flag[v] = 1;
                }
            }
        }
    }
    return false;
}

void work(){
    cin >> H >> W;
    Board.assign(H, "");
    for(auto & s : Board) cin >> s;
    
    cin >> N;
    E.assign(N, {});
    Pos2Vertex.clear();
    Energy.assign(H, vi(W, 0));
    int k = 0;
    for(auto & p : E){
        cin >> p.first.first >> p.first.second >> p.second;
        p.first.first -= 1; p.first.second -= 1;
        Energy[p.first.first][p.first.second] = p.second;
        Pos2Vertex.insert({p.first, ++k});
    }
    cout << (proc() ? "Yes\n" : "No\n");
    return;
}

int main(){
#ifndef ONLINE_JUDGE
    freopen("z.txt", "r", stdin);
#endif
    ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    int nofkase = 1;
    // cin >> nofkase;
    while(nofkase--) work();
    return 0;
}